#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>

struct diffLinePara
{
	int label = -1;
	double length = -1;
	double angle = -1;
	double upcol_edge = -1;
};

struct linePara
{
	cv::Vec4i points;
	double angle = -1;
	double slope = -1;
	double b = -1;
	double length = -1;
	double upcol_edge = -1;
	int label = -1;
};

class LaneDetection
{
public:
	void read_imgs(std::vector<cv::Mat>& img_inputs_);
	void rgb_gray(cv::Mat& img_input_, cv::Mat& img_output_);
	void adaptive_threshold(cv::Mat& img_input_, cv::Mat& img_output_);
	void rgb_to_hls(cv::Mat& img_input_, cv::Mat& img_output_);
	void connect_component(cv::Mat& img_input_, cv::Mat& img_output_);
	void filter_img(cv::Mat& img_input_, cv::Mat& img_output_);
	void fill_mean(cv::Mat& img_input_);
	void lane_roi(cv::Mat& img_input_, cv::Mat& img_roi_, cv::Point* pts_);
	void roi_points(cv::Mat& img_input_, cv::Point* pts_, double row_prec_=0.3);
	void perspective_transform(cv::Mat& img_input_, cv::Mat& img_output_, cv::Point* pts_, double row_prec_);
	std::vector<std::vector<cv::Vec4i>> line_separa(std::vector<cv::Vec4i> lines, cv::Mat& img_edges);
	std::vector<cv::Point> regression(std::vector<std::vector<cv::Vec4i> > left_right_lines, cv::Mat& img_input_);
	int find_contour(cv::Mat& img_input_, cv::Mat& img_output_, int val_);

	std::vector<cv::Vec4i> detect_reduce_lines(cv::Mat& img_input_, cv::Mat& img_output_);
	bool extend_bound_rectangle_line_equivalence(const cv::Vec4i& l1_, const cv::Vec4i& l2_, 
			float exten_length_fraction, float max_angle_diff, float bound_rectangle_thickness);
	cv::Vec4i extend_line(cv::Vec4i line, double len);
	cv::Vec2d linear_parameters(cv::Vec4i line);
	std::vector<cv::Point2i> bound_rectangle_contour(cv::Vec4i line, float d);
	std::vector<cv::Vec4i> filter_lines(std::vector<cv::Vec4i> lines_, cv::Mat& img_input_, std::vector<linePara>& line_paras_);
	std::vector<cv::Vec4i> differ_lines(std::vector<cv::Vec4i> lines, cv::Mat& img_input_, std::vector<linePara>& line_paras_);
	void line_point_image_border(const cv::Point &p1_in, const cv::Point &p2_in, cv::Point &p1_out,
									cv::Point &p2_out, int rows, int cols);
	void line_mask(std::vector<cv::Vec4i> lines, cv::Mat& img_input_);
	void line_mask(std::vector<linePara> line_paras_, cv::Mat& img_input_);

private:
	std::string img_path = "./vlc_img/*.png";

};

//g++ -std=c++14 lane_detection.cpp -o lane_detection -lopencv_core -lopencv_highgui -lopencv_videoio -lopencv_imgproc -lopencv_imgcodecs


